import { HttpHeaderValue, HttpRequestHeader, RequestHeader } from './HttpHeader'
import { HttpMethod } from './HttpMethod'
import { HttpQuery, HttpRequest } from './HttpRequest'
import { HttpVersion } from './HttpVersion'

/**
 * HttpRequestBuild
 * @author 冰凝
 * @date 2022-07-01 下午 05:50
 **/

export class HttpRequestBuild<T = string> {
    // HTTP 协议参数
    /**
     * 协议版本
     */
    private _version: HttpVersion
    /**
     * 请求方法
     */
    private _method: HttpMethod
    /**
     * 请求路径
     */
    private _path: string
    /**
     * 查询参数 (?之后)
     */
    private _query: HttpQuery
    /**
     * URL 锚点参数 (#之后)
     */
    private _anchor: string
    /**
     * 请求 Header
     */
    private _header: HttpRequestHeader
    /**
     * 请求体
     */
    private _body: T

    // 请求控制参数
    /**
     * 请求超时, 单位: 毫秒
     */
    private _timeout: number
    /**
     * 读取超时, 单位: 毫秒
     */
    private _readTimeout: number

    constructor(version: HttpVersion = HttpVersion.HTTP_1_1) {
        this._version = version
    }

    public version(version: HttpVersion = HttpVersion.HTTP_1_1) {
        this._version = version
        return this
    }

    public method(method: HttpMethod) {
        this._method = method
        return this
    }

    public url(url: string) {
        this._path = url
        return this
    }

    public query(query: HttpQuery) {
        this._query = query

        return this
    }

    public addQuery(key: string, value: string | number | boolean | Array<string>) {
        if (!this._query) {
            this._query = new Map<string, string | Array<string>>()
        }
        if (this._query instanceof Map) {
            this._query.set(key, value as string | Array<string>)
        } else {
            this._query[key] = value as string | Array<string>
        }

        return this
    }

    public header(header: HttpRequestHeader) {
        this._header = header
        return this
    }

    public addHeader(key: RequestHeader | string, value: HttpHeaderValue) {
        if (!this._header) {
            this._header = new Map<RequestHeader | string, HttpHeaderValue>
        }
        if (this._header instanceof Map) {
            this._header.set(key, value)
        } else {
            this._header[key] = value
        }

        return this
    }

    public anchor(anchor: string) {
        this._anchor = anchor
        return this
    }

    public body(data: T) {
        this._body = data
        return this
    }

    public timeout(time: number) {
        this._timeout = time
        return this
    }

    public timeoutSecond(second: number) {
        this._timeout = second * 1000
        return this
    }

    public readTimeout(time: number) {
        this._readTimeout = time
        return this
    }

    public readTimeoutSecond(second: number) {
        this._readTimeout = second * 1000
        return this
    }

    public build(): HttpRequest<T> {
        const request = new HttpRequest<T>()
        request.version = this._version
        request.method = this._method
        request.path = this._path
        request.query = this._query
        request.anchor = this._anchor
        request.header = this._header
        request.body = this._body
        request.timeout = this._timeout
        request.readTimeout = this._readTimeout

        return request
    }
}
